#!/usr/bin/env ruby

require 'fileutils'
require 'yaml'
require 'pathname'

unless defined? ROR_SERVICE_ROOT
  ROR_SERVICE_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
  $:.unshift(ROR_SERVICE_ROOT)
end

require 'container/mongrel_instance'
require 'container/utils'

class MongrelController

  include Utils

  @@verbose = false
  def MongrelController.be_verbose
    @@verbose = true
  end
  
  include FileUtils

  def self.start_from_config_file(config_file)
    mongrel = MongrelInstance.parse_config_path(config_file)
    # TODO unfinished
    mongrel.start
  end

  def self.for_domain(domain)
    new(File.join(ROR_SERVICE_ROOT, 'config', 'sites', domain))
  end

  def initialize(container_root)
    @container_root = Pathname.new(container_root).realpath.to_s
  end

  def create_container(host_or_hosts, port_or_ports)

    mkdir_p application_root
    mkdir_p content_dir
    mkdir_p config_dir
    
    hosts = to_array(host_or_hosts)
    ports = to_array(port_or_ports)

    hosts.each do |host|
      touch File.join(config_dir, "monit.#{host}.init.config")
      ports.each_with_index do |port, index|
        reserve = (index != 0)
        mongrel = MongrelInstance.new(self, host, port, reserve)
        mongrel.generate_config
      end
    end
  end

  def start(host = nil, port = nil)
    return false unless rails_app_installed?

    all_ok = true
    mongrel_fully_specified = (host and port)
    mongrels_to_start =
        if mongrel_fully_specified then [MongrelInstance.find_one(self, :host => host, :port => port)]
        else MongrelInstance.find_active(self, :host => host, :port => port) end

    mongrels_to_start.each do |mongrel|
      all_ok = false unless mongrel.start
    end

    return all_ok
  end

  def stop(host = nil, port = nil)
    MongrelInstance.find_all(self, :host => host, :port => port).each do |mongrel|
      mongrel.stop
    end
  end

  def restart(host = nil, port = nil)
    stop(host, port)
    start
  end

  def application_root
    File.join(@container_root, 'web', 'rails')
  end

  def content_dir
    File.join(@container_root, 'web', 'content')
  end

  def config_dir
    File.join(@container_root, 'config')
  end

  def root
    @container_root
  end

  def rails_app_installed?
    ['public/dispatch.rb', 'log/', 'tmp/', 'public/'].each do |path|
      unless File.exists?(File.join(application_root, path))
        puts "Not found: #{path}. Rails application is either not installed, or installed incorrectly, in this container" if @@verbose
        return false
      end
    end

    return true
  end

  def to_array(obj)
    case obj
    when Array then obj
    when Range then obj.to_a
    else [obj]
    end
  end

end

if $0 == __FILE__
  action, container_root, host, port, user = ARGV

  errors = []
  errors << "action and container root are mandatory parameters" unless action and container_root
  errors << "Unknown action: #{action}" unless %w(create_container start stop restart).include? action
  errors << "host, port and user must be specified for generate_config" if action == 'generate_config' and user.nil?

  unless errors.empty?
    errors.unshift "Usage: mongrel_controller.rb create_container|start|stop|restart <path to container root> [<host> [<port number> [<user>]]]"
    STDERR.puts errors
    exit 1
  end

  MongrelController.be_verbose
  if action == 'create_container'
    MongrelController.new(container_root).create_container
  else
    MongrelController.new(container_root).send(action, host, port)
  end

end
